package com.ysten.basic.web.business;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.BlockingQueue;

import javax.annotation.PostConstruct;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import com.google.common.collect.Queues;
import com.taobao.api.ApiException;
import com.taobao.api.DefaultTaobaoClient;
import com.taobao.api.TaobaoClient;
import com.taobao.api.request.AlibabaAliqinFcSmsNumSendRequest;
import com.taobao.api.response.AlibabaAliqinFcSmsNumSendResponse;
import com.ysten.basic.bean.entity.business.Sms;
import com.ysten.basic.common.utils.SystemConfigLoader;
import com.ysten.basic.service.business.SmsService;

/**
 * <发送短信任务>
 * 
 * @author 陆小凤
 * @version [版本号, 2015年11月12日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Lazy(false)
@Slf4j
@Component("smsSendApiWorker")
public class SmsSendApiWorker
{
    @Autowired
    private SystemConfigLoader systemConfigLoader;
    
    @Autowired
    private SmsService smsService;
    
    private BlockingQueue<Sms> sendSmsQueue = Queues.newLinkedBlockingQueue(1024);
    
    private TaobaoClient client;
    
    private AlibabaAliqinFcSmsNumSendRequest req = new AlibabaAliqinFcSmsNumSendRequest();
    
    private AlibabaAliqinFcSmsNumSendResponse rsp;
    
    /**
     * <@PostConstruct是Java EE
     * 5引入的注解，Spring允许开发者在受管Bean中使用它。当DI容器实例化当前受管Bean时，@PostConstruct注解的方法会被自动触发，从而完成一些初始化工作，示例代码如下>
     * 
     * @see [类、类#方法、类#成员]
     */
    @PostConstruct
    public void init()
    {
        log.info("Enter func[init].");
        String url = systemConfigLoader.getStringValue("sms.url");
        String appKey = systemConfigLoader.getStringValue("sms.appKey");
        String appSecret = systemConfigLoader.getStringValue("sms.appSecret");
        // 初始化发送短信连接
        client = new DefaultTaobaoClient(url, appKey, appSecret);
        
        Thread worker = new Thread(new ExeSendSmsWorker());
        worker.setUncaughtExceptionHandler(new ErrHandler());
        worker.start();
    }
    
    private class ExeSendSmsWorker implements Runnable
    {
        @Override
        public void run()
        {
            System.out.println("线程开启!!!!");
            boolean isContinue = true;
            while (isContinue)
            {
                try
                {
                    Sms sms = sendSmsQueue.take();
                    if (null != sms)
                    {
                        StringBuffer sb = new StringBuffer();
                        sb.append("{\"code\":\"【");
                        sb.append(sms.getSmsParamCode());
                        sb.append("】\",\"product\":\"【");
                        sb.append(sms.getSmsParamProduct());
                        sb.append(" 】\",\"item\":\"【");
                        sb.append(sms.getSmsParamItem());
                        sb.append("】\"}");
                        req.setExtend(sms.getExtend());
                        req.setSmsType(sms.getSmsType());
                        req.setSmsFreeSignName(sms.getSmsFreeSignName());
                        req.setSmsParamString(sb.toString());
                        req.setRecNum(sms.getRecNum());
                        req.setSmsTemplateCode(sms.getSmsTemplateCode());
                        rsp = client.execute(req);
                        sms.setSmsResult(rsp.getBody());
                        smsService.save(sms);
                    }
                }
                catch (InterruptedException e)
                {
                    init();
                    isContinue = false;
                }
                catch (ApiException e)
                {
                    e.printStackTrace();
                }
            }
            
        }
        
    }
    
    private class ErrHandler implements UncaughtExceptionHandler
    {
        
        @Override
        public void uncaughtException(Thread thread, Throwable throwable)
        {
            log.error("thread name:[{}],throwable stackTrace:[{}]",
                thread.getName(),
                ExceptionUtils.getStackFrames(throwable));
        }
    }
    
    public void putToQueue(Sms sms)
    {
        try
        {
            this.sendSmsQueue.put(sms);
        }
        catch (InterruptedException e)
        {
            log.error("Inner func[putSendSms], catch InterruptedException while put sendLcims to sendSmsQueue. {}", e);
        }
        catch (Exception e)
        {
            log.error("Inner func[putSendSms], catch execption while put sendLcims to sendSmsQueue. {}", e);
        }
    }
    
}